﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Service;
using MODEL;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Messaging;
using System.Windows.Input;
using GalaSoft.MvvmLight.Command;
using Microsoft.Practices.ServiceLocation;
using GalaSoft.MvvmLight.Views;
using Common;
using System.ComponentModel;
using GalaSoft.MvvmLight.Ioc;

namespace ViewModel.StationManager
{
    public class StationSettingEditViewModel : ViewModelBase
    {
        private const int StationValveCount = 5;

        public ICommand SaveCommand { get; set; }

        private StationInfo m_StationInfo = new StationInfo();
        public StationInfo StationInfo
        {
            get { return this.m_StationInfo; }
            set { this.m_StationInfo = value; base.RaisePropertyChanged(() => this.StationInfo); }
        }

        private List<ValveCheckModel> m_ValveCheckList = new List<ValveCheckModel>();
        public List<ValveCheckModel> ValveCheckList
        {
            get { return this.m_ValveCheckList; }
            set { this.m_ValveCheckList = value; base.RaisePropertyChanged(() => ValveCheckList); }
        }

        private static readonly string NonSelectStationType = "未选中站点类型";
        private string m_CurrentStationType;
        public string CurrentStationType
        {
            get { return this.m_CurrentStationType; }
            set { this.m_CurrentStationType = value; base.RaisePropertyChanged(() => CurrentStationType); }
        }
        private List<string> m_StationTypeList;
        public List<string> StationTypeList
        {
            get { return this.m_StationTypeList; }
            set { this.m_StationTypeList = value; base.RaisePropertyChanged(() => this.StationTypeList); }
        }

        private static readonly Province NonSelectProvince = new Province { ProvinceName = "未选中省" };
        private Province m_CurrentProvince;
        public Province CurrentProvince
        {
            get { return this.m_CurrentProvince; }
            set { m_CurrentProvince = value; base.RaisePropertyChanged(() => this.CurrentProvince); }
        }
        private List<Province> m_ProvinceList;
        public List<Province> ProvinceList
        {
            get { return this.m_ProvinceList; }
            set { this.m_ProvinceList = value; base.RaisePropertyChanged(() => this.ProvinceList); }
        }

        private static readonly City NonSelectCity = new City { CityName = "未选中市" };
        private City m_CurrentCity;
        public City CurrentCity
        {
            get { return this.m_CurrentCity; }
            set { this.m_CurrentCity = value; base.RaisePropertyChanged(() => this.CurrentCity); }
        }
        private List<City> m_CityList;
        public List<City> CityList
        {
            get { return this.m_CityList; }
            set { this.m_CityList = value; base.RaisePropertyChanged(() => this.CityList); }
        }

        private static readonly County NonSelectCounty = new County { CountyName = "未选中区" };
        private County m_CurrentCounty;
        public County CurrentCounty
        {
            get { return this.m_CurrentCounty; }
            set { this.m_CurrentCounty = value; base.RaisePropertyChanged(() => this.CurrentCounty); }
        }
        private List<County> m_CountyList;
        public List<County> CountyList
        {
            get { return this.m_CountyList; }
            set { this.m_CountyList = value; base.RaisePropertyChanged(() => this.CountyList); }
        }

        private Dictionary<int, string> m_OpenStatusDic;
        public Dictionary<int, string> OpenStatusDic {
            get { return this.m_OpenStatusDic; }
            set { this.m_OpenStatusDic = value; base.RaisePropertyChanged(() => this.OpenStatusDic); }
        }    

        private string m_HardWareId1;
        public string HardWareId1
        {
            get { return this.m_HardWareId1; }
            set { this.m_HardWareId1 = value; base.RaisePropertyChanged(() => HardWareId1); }
        }

        private string m_HardWareId2;
        public string HardWareId2
        {
            get { return this.m_HardWareId2; }
            set { this.m_HardWareId2 = value; base.RaisePropertyChanged(() => HardWareId2); }
        }

        private string m_HardWareId3;
        public string HardWareId3
        {
            get { return this.m_HardWareId3; }
            set { this.m_HardWareId3 = value; base.RaisePropertyChanged(() => HardWareId3); }
        }

        private string m_HardWareId4;
        public string HardWareId4
        {
            get { return this.m_HardWareId4; }
            set { this.m_HardWareId4 = value; base.RaisePropertyChanged(() => HardWareId4); }

        }

        private IStationServcie m_StationService;
        private IAreaService m_AreaService;

        public StationSettingEditViewModel(IStationServcie stationService, IAreaService areaServuce)
        {
            this.m_StationService = stationService;
            this.m_AreaService = areaServuce;

            this.SaveCommand = new RelayCommand(SaveStationInfo);

            RefreshData(()=>this.PropertyChanged += this.OnPropertyChange);
        }

        private Dictionary<int, List<City>> m_CityDictionary;
        private Dictionary<int, List<County>> m_CountyDictionary;

        public void OnPropertyChange(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "StationInfo")
            {
                if (!string.IsNullOrWhiteSpace(this.StationInfo.Valve_NoListStr))
                {
                    string[] valveCheckStrList = this.StationInfo.Valve_NoListStr.Split('>');
                    foreach (string valveCheckStr in valveCheckStrList)
                    {
                        
                        string[] valveStrSplitResult = valveCheckStr.Split(':');
                        if (valveStrSplitResult.Length != 2 || valveStrSplitResult.Any(str => string.IsNullOrEmpty(str)))
                        {
                            continue;
                        }
                        int number = int.Parse(valveStrSplitResult[0]), operate = int.Parse(valveStrSplitResult[0]);

                        ValveCheckModel valveCheckModel = this.ValveCheckList.FirstOrDefault(model => model.Number == number);
                        if (valveCheckModel == null)
                        {
                            continue;
                        }
                        valveCheckModel.IsChecked = true;
                        valveCheckModel.CurrentSelectedOperation = valveCheckModel.StationOperateList.FirstOrDefault(operation => operation.Key == operate);                       
                    }
                }

                if (!string.IsNullOrEmpty(StationInfo.HardWareId))
                {
                    string[] hardWareIdSplitResult = StationInfo.HardWareId.Split('.');
                    if (hardWareIdSplitResult.Length == 4)
                    {
                        this.HardWareId1 = hardWareIdSplitResult[0];
                        this.HardWareId2 = hardWareIdSplitResult[1];
                        this.HardWareId3 = hardWareIdSplitResult[2];
                        this.HardWareId4 = hardWareIdSplitResult[3];
                    }
                }

                if (!string.IsNullOrEmpty(StationInfo.ProvinceName))
                {
                    this.CurrentProvince = this.ProvinceList.FirstOrDefault(province => province.ProvinceName == StationInfo.ProvinceName);
                }

                if (!string.IsNullOrEmpty(StationInfo.CityName))
                {
                    this.CurrentCity = this.CityList.FirstOrDefault(city => city.CityName == StationInfo.CityName);
                }

                if (!string.IsNullOrEmpty(StationInfo.CountyName))
                {
                    this.CurrentCounty = this.CountyList.FirstOrDefault(county => county.CountyName == StationInfo.CountyName);
                }

                if (!string.IsNullOrEmpty(StationInfo.StationType))
                {
                    this.CurrentStationType = this.StationTypeList.FirstOrDefault(stationType => stationType.Equals(StationInfo.StationType, StringComparison.OrdinalIgnoreCase));
                }
            }

            if (e.PropertyName == "CurrentProvince")
            {
                List<City> cityList = new List<City>() { NonSelectCity };
                if (this.CurrentProvince != NonSelectProvince)
                {
                    List<City> citys = new List<City>();
                    if (this.m_CityDictionary.TryGetValue(this.CurrentProvince.Id, out citys))
                    {
                        cityList.AddRange(citys);
                    }
                }
                this.CityList = cityList;
            }

            if (e.PropertyName == "CurrentCity")
            {
                List<County> countyList = new List<County> { NonSelectCounty };
                if (this.CurrentCity != NonSelectCity)
                {
                    List<County> countys = new List<County>();
                    if (this.m_CountyDictionary.TryGetValue(this.CurrentCity.CityId, out countys))
                    {
                        countyList.AddRange(countys);
                    }
                }
                this.CountyList = countyList;
            }
       
        }

        public async void RefreshData(Action afterAction = null)
        {
            try
            {
                List<KeyValuePair<int, string>> stationOperateList = new List<KeyValuePair<int, string>> { ValveCheckModel.NonSelectedOperation };
                stationOperateList.AddRange(EnumHelper.ConvertEnumToKeyValueList(typeof(StationOperateTypeEnum)));

                List<ValveCheckModel> valveCheckList = new List<ValveCheckModel>();
                for (int i = 0; i < StationValveCount; i++)
                {
                    valveCheckList.Add(new ValveCheckModel
                    {
                        Number = i + 1,
                        CurrentSelectedOperation = ValveCheckModel.NonSelectedOperation,
                        StationOperateList = stationOperateList
                    });
                }
                this.ValveCheckList = valveCheckList;

                List<string> stationTypeList = new List<string> { NonSelectStationType };
                stationTypeList.AddRange(EnumHelper.GetEnumDescriptionList(typeof(StationTypeEnum)));
                this.StationTypeList = stationTypeList;

                this.OpenStatusDic = EnumHelper.ConvertEnumToDictionary(typeof(OpenStatusEnum));

                List<Province> provinces = new List<Province>() { NonSelectProvince };
                provinces.AddRange(await m_AreaService.GetAllProvinceList());
                this.ProvinceList = provinces;

                this.CityList = new List<City> { NonSelectCity };
                this.CountyList = new List<County> { NonSelectCounty };

                this.m_CityDictionary = (await m_AreaService.GetAllCityList()).GroupBy(city => city.ProvinceId).ToDictionary(cityGroyup => cityGroyup.Key, cityGroup => cityGroup.ToList());

                this.m_CountyDictionary = (await m_AreaService.GetAllCountyList()).GroupBy(county => county.CityId).ToDictionary(countyGroup => countyGroup.Key, countyGroup => countyGroup.ToList());

                this.CurrentStationType = NonSelectStationType;
                this.CurrentProvince = NonSelectProvince;
                this.CurrentCity = NonSelectCity;
                this.CurrentCounty = NonSelectCounty;

                if (afterAction != null)
                {
                    afterAction.Invoke();
                }
            }
            catch (Exception ex)
            {
                await ServiceLocator.Current.GetInstance<IDialogService>().ShowError("加载数据失败", "错误", "确定", null);
                Log.WriteException(ex);
            }
        }

        public async void SaveStationInfo()
        {
            if (string.IsNullOrWhiteSpace(StationInfo.StationName))
            {
                await ServiceLocator.Current.GetInstance<IDialogService>().ShowMessage("站点名称不能未空", "校验失败");
                return;
            }

            if (string.IsNullOrWhiteSpace(StationInfo.StationCode))
            {
                await ServiceLocator.Current.GetInstance<IDialogService>().ShowMessage("站点编码不能未空", "校验失败");
                return;
            }

            if (CurrentStationType == NonSelectStationType)
            {
                await ServiceLocator.Current.GetInstance<IDialogService>().ShowMessage("必须选择一种设备类型", "校验失败");
                return;
            }

            if (!string.IsNullOrEmpty(this.StationInfo.Ip) && !this.StationInfo.Ip.IsIPAddress())
            {
                await ServiceLocator.Current.GetInstance<IDialogService>().ShowMessage("IP地址不正确，请修改(例：127.0.0.1)", "校验失败");
                return;
            }

            if (new[] { HardWareId1, HardWareId2, HardWareId3, HardWareId4 }.Any(str => string.IsNullOrWhiteSpace(str) || !str.IsInt()))
            {
                await ServiceLocator.Current.GetInstance<IDialogService>().ShowMessage("设备Id必须为数字且不能为空", "校验失败");
                return;
            }

            foreach (var item in this.ValveCheckList)
            {
                if (item.IsChecked && item.CurrentSelectedOperation.Key == ValveCheckModel.NonSelectedOperation.Key)
                {
                    await ServiceLocator.Current.GetInstance<IDialogService>().ShowMessage($"{item.Name}必须选择一种操作类型", "校验失败");
                    return;
                }
            }
            
            StationInfo stationInfo = this.StationInfo;
            if (this.CurrentStationType != NonSelectStationType)
            {
                stationInfo.StationType = this.CurrentStationType;
            }

            if (CurrentProvince != NonSelectProvince)
            {
                stationInfo.ProvinceName = this.CurrentProvince.ProvinceName;
            }

            if (CurrentCity != NonSelectCity)
            {
                stationInfo.CityName = this.m_CurrentCity.CityName;
            }

            if (CurrentCounty != NonSelectCounty)
            {
                stationInfo.CountyName = this.m_CurrentCounty.CountyName;
            }
            
            stationInfo.HardWareId = string.Join(".", new[] { this.HardWareId1, this.HardWareId2, this.HardWareId3, this.HardWareId4 });
            stationInfo.HardWareCode = (long)(int.Parse(this.HardWareId1) * Math.Pow(2, 16) + int.Parse(this.HardWareId2) * Math.Pow(2, 12) + int.Parse(this.HardWareId3) * Math.Pow(2, 6) + int.Parse(this.HardWareId4));

            stationInfo.Valve_NoListStr = string.Join(">", this.ValveCheckList.Where(model => model.IsChecked).Select(model => $"{model.Number}:{model.CurrentSelectedOperation.Key}"));

            try
            {
                Task task = this.m_StationService.InsertOrUpdateStationAsync(stationInfo);
                task.Wait();
                await ServiceLocator.Current.GetInstance<IDialogService>().ShowMessage("保存成功", "校验失败");

                this.MessengerInstance.Send<object>(null, "StationSettingEdit_CloseForm");
            }
            catch (Exception ex)
            {
                await ServiceLocator.Current.GetInstance<IDialogService>().ShowError("保存失败", "错误", "确定", null);
                Log.WriteException(ex);
            }
        }
    }

    public class ValveCheckModel:ViewModelBase,ICheck
    {
        private bool m_IsChecked;
        public bool IsChecked
        {
            get { return this.m_IsChecked; }
            set { this.m_IsChecked = value; base.RaisePropertyChanged(() => this.IsChecked); }
        }

        public int Number { get; set; }
        public string Name => "阀门" + Number.ToString();

        public static readonly KeyValuePair<int,string> NonSelectedOperation = new KeyValuePair<int,string>(0, "请选择操作类型");
        private KeyValuePair<int,string> m_CurrentSelectedOperation;
        public KeyValuePair<int,string> CurrentSelectedOperation
        {
            get { return this.m_CurrentSelectedOperation; }
            set { this.m_CurrentSelectedOperation = value; base.RaisePropertyChanged(() => this.CurrentSelectedOperation); }
        }

        
        public List<KeyValuePair<int,string>> StationOperateList { get; set; }
    }
}
